package com.jketing.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.imageio.ImageIO;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jketing.annotation.FieldMeta;

/**
 * BaseController 请求处理基类
 * 
 * 主要用于表单提交数据的在传给service层之前进行一些处理
 * 或service返回数据到表单的处理
 * 
 * @author  李荣华
 * @version v1.0
 * @date    2017-11-22
 * @since   Spring-mvc 4.3.8
 */
public abstract class BaseController {
	protected Field[] getAllFields(Class<?> clazz){
		  //Class<?> clazz = object.getClass();
		  List<Field> fieldList = new ArrayList<>();
		  while (clazz != null){
		    fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
		    clazz = clazz.getSuperclass();
		  }
		  Field[] fields = new Field[fieldList.size()];
		  fieldList.toArray(fields);
		  return fields;
		}
	
	/**
	 * checkObjFieldIsNotNull:校验对象属性是否全为null
	 */
	protected boolean checkObjFieldIsNotNull(Object obj){
	    try {
	    	Field[] fields = getAllFields(obj.getClass());
	        for (Field f : fields) {
	            f.setAccessible(true);
	            if("serialVersionUID".equals(f.getName())||Set.class==f.getType()) {
	            	continue;
	            }
	            if (f.get(obj) != null) {
	                return true;
	            }
	        }
	    }catch (IllegalAccessException e){

	    }
	    return false;
	}
	
	public <S extends Object> S setObjectEmptyFieldToNull(S object) {
		if (object != null && !"".equals(object)) {
			try {
				Map<String, String> map = BeanUtils.describe(object);
				Set<String> keySet = map.keySet();
				for (Iterator<String> iter = keySet.iterator(); iter.hasNext();) {
					String element = iter.next();
					String temp = map.get(element);
					if (!"class".equals(element)) {
						String keyClass = PropertyUtils.getPropertyType(object,element).getName();
						if ("java.lang.String".equals(keyClass)) { // 处理非Bean类型
							if(StringUtils.isBlank(temp)) {
								PropertyUtils.setProperty(object, element, null);
							}
						} 
						else if(keyClass.contains("com.")) {// 处理类型为Bean的属性
							 Object quote = PropertyUtils.getProperty(object, element.toString());//处理引用的Bean属性
							 if(quote!=null && !checkObjFieldIsNotNull(quote)) {
								 PropertyUtils.setProperty(object,element,null);
							 }
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return object;
	}
	
	/**
	 * 将图片文件转换后输出
	 * @throws IOException 
	 */
	public static void zoomImage(InputStream input, String tagFileName,
			int width, int height) throws IOException {
		BufferedImage bi = ImageIO.read(input);
		BufferedImage tag = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		tag.getGraphics().drawImage(bi, 0, 0, width, height, null);
		ImageIO.write(tag, "jpg", new File(tagFileName));
	}
	
	public byte[] getPhotoBytes(MultipartFile file, long countKB, int width,
			int height) throws IOException {
		byte b[] = null;
		if (file.getSize() >= countKB * 1024) {
			String folder = System.getProperty("java.io.tmpdir");
			String outFileName = "upload.jpg";
			File outFile = null;
			InputStream input = null;
			zoomImage(file.getInputStream(), folder + outFileName, width, height); // 将图片文件转换后输出
			outFile = new File(folder + outFileName);
			input = new FileInputStream(outFile);
			b = new byte[(int)outFile.length()];
			input.read(b);
			input.close();
			outFile.delete();
		}else {
			b = file.getBytes();
		}
		return b;
	}
	
	public void entityQueryFields(Class<?> clazz,String key,String value,Map<String,String> map){
		Field[] fields = getAllFields(clazz);
        for (Field field : fields) {
        	 //获取字段中包含fieldMeta的注解  
        	if(field.isAnnotationPresent(FieldMeta.class)){
        		FieldMeta meta = field.getAnnotation(FieldMeta.class);
        		if(meta.name().contains("Entity")) {
        			entityQueryFields(field.getType(),key + meta.name() + ":",value + meta.explain() + ".",map);
        		}else {
        			map.put(key + meta.name(),value + meta.explain());
        		}
        	}
        }
	}
	
	/**
	 *  findQueryFields 得到动态查询字段
	 *  
	 *  
	 *  @param	Class<?> clazz	查询实体的类型
	 *  
	 *  @return Map<String,String>	
	 */
	public Map<String,String> findQueryFields(Class<?> clazz){
		Map<String,String> map = new HashMap<String,String>();
		Field[] fields = getAllFields(clazz);
        for (Field field : fields) {
        	 //获取字段中包含fieldMeta的注解  
        	if(field.isAnnotationPresent(FieldMeta.class)){
        		FieldMeta meta = field.getAnnotation(FieldMeta.class);        		
        		if(meta.name().contains("Entity")) {
        			String key = meta.name() + ":";
        			String value = meta.explain() + ".";
        			Class<?> fieldClazz = field.getType(); // 得到field的class及类型全路径          			  
        		    //if(fieldClazz.isPrimitive())  continue;  //【1】 //判断是否为基本类型          		  
        		    //if(fieldClazz.getName().startsWith("java.lang")) continue; //getName()返回field的类型全路径；  
        			if(fieldClazz.isAssignableFrom(Set.class)) {   
        		             Type fc = field.getGenericType(); // 关键的地方，如果是Set类型，得到其Generic的类型
        		             if(fc == null) continue;  
        		             if(fc instanceof ParameterizedType){ // 【3】如果是泛型参数的类型      
        		                   ParameterizedType pt = (ParameterizedType) fc;          		  
        		                   Class<?> genericClazz = (Class<?>)pt.getActualTypeArguments()[0]; //【4】 得到泛型里的class类型对象。          		  
        		                   entityQueryFields(genericClazz,key,value,map);
        		             }   
        		      }else{
        		    	  entityQueryFields(fieldClazz,key,value,map);
        		      } 
        		}else {
        			map.put(meta.name(), meta.explain());
        		}
        	}
        }
		return map;
	}
	
	public String toJson(Object obj) throws JsonProcessingException {
		ObjectMapper mapper = new ObjectMapper(); 
		return mapper.writeValueAsString(obj);
	}
	
	public Map<String,String> findOperatorsForString(){
		Map<String,String> map = new HashMap<String,String>();
		map.put("=", "等于");
		map.put(">", "大于");
		map.put(">=", "大于等于");
		map.put("<", "小于");
		map.put("<=", "小于等于");
		map.put("<>", "不等于");
		map.put("between", "在什么之间");
		map.put("~between", "不在什么之间");		
		map.put("in", "在集合中");
		map.put("~in", "不在集合中");
		map.put("isNull", "为Null");
		map.put("isNotNull", "不为Null");
		map.put("X%", "以什么开头");
		map.put("%X", "以什么结尾");
		map.put("%X%", "包含");
		map.put("X%", "以什么开头");
		map.put("%X", "以什么结尾");
		map.put("%X%", "包含");
		map.put("~X%", "不以什么开头");
		map.put("~%X", "不以什么结尾");
		map.put("~%X%", "不包含");
		return map;
	}
	
	public Map<String,String> findOperators(){
		Map<String,String> map = new HashMap<String,String>();
		map.put("=", "等于");
		map.put(">", "大于");
		map.put(">=", "大于等于");
		map.put("<", "小于");
		map.put("<=", "小于等于");
		map.put("<>", "不等于");
		map.put("between", "在什么之间");
		map.put("~between", "不在什么之间");		
		map.put("in", "在集合中");
		map.put("~in", "不在集合中");
		map.put("isNull", "为Null");
		map.put("isNotNull", "不为Null");
		return map;
	}
}
